package gbench.sandbox.matlib;

import org.junit.jupiter.api.Test;

import java.util.LinkedList;
import java.util.Optional;

import gbench.common.matlib.MatlibCanvas.NVec;
import gbench.common.matlib.MatlibCanvas.Seq;
import gbench.common.matlib.matrix.Complex;
import gbench.common.matlib.matrix.ComplexMatrix;
import gbench.common.tree.LittleTree;

import static gbench.common.matlib.MatlibCanvas.println;
import static gbench.common.tree.LittleTree.compose_f;

/**
 * 序列集合的使用演示
 * @author gbench
 *
 */
public class JunitSeq {
    
    /**
     * 路径提取
     */
    @Test
    public void pathget(){
        final var dd  = ComplexMatrix.of(10, 10, 1,2,3,4,5,6,7).transpose();
        println("dd:\n",dd);
        final var cc = ComplexMatrix.of(10, 10, Complex::C);
        println("cc:\n",cc);
        println("eval:",cc.eval(e->e.pathget(1,1)));
        println("eval:",cc.eval(e->e.pathget2(Complex.NaN,1,1,1)));
    }
    
    /**
     * 数据维度探查
     */
    @Test
    public void analyze() {
        println("\n数据维度/层级探查","-----------------------------------------");
        final var tt = NVec.of(27, i -> i).reshape(3, 3, 3);
        final var seq = Seq.SEQ(tt, true); // 把一个对象转换成Seq结构
        println("seq:", seq.format());
        seq.analyze(1, 1, 1, 1).map(LittleTree.kvp_int()).forEach(kvp -> { // 多出一个空的维度
            println("comp:", kvp._1(), kvp._2().map(compose_f(Seq::format, Seq::SEQ)).orElse(null));
        });
        println("\n序列数据的逆序遍历","-----------------------------------------");
        seq.analyze(1, 1, 1, 1).reverseStream().dropWhile(Optional::isEmpty).forEach(e->{
            System.out.println(e.map(compose_f(Seq::format, Seq::SEQ)).orElse(null));
        });
        
        println("Seq.SEQ(1)",Seq.SEQ(1).format());
        println("Seq.SEQ(new Integer[1])",Seq.SEQ(new Integer[] {1}).format());
        
        println("Seq.SEQ(new byte[1])",Seq.SEQ(new byte[]{'c'}).format());
        println("Seq.SEQ(new char[1])",Seq.SEQ(new char[]{'c'}).format());
        println("Seq.SEQ(new boolean[1])",Seq.SEQ(new boolean[]{true}).format());
        
        println("Seq.SEQ(new int[1])",Seq.SEQ(new int[]{1}).format());
        println("Seq.SEQ(new short[1])",Seq.SEQ(new short[] {1}).format());
        println("Seq.SEQ(new long[1])",Seq.SEQ(new long[] {1L}).format());
        println("Seq.SEQ(new float[1])",Seq.SEQ(new float[]{1F}).format());
        println("Seq.SEQ(new double[1])",Seq.SEQ(new double[]{1D}).format());
    }
    
    /**
     * 数据切片
     */
    @Test
    public void slice() {
        Seq<Double> seq = () -> NVec.of(100, i -> i).dblA();
        final var queue = new LinkedList<Seq<Double>>();// 使用队列对数据进行分组:前头的是需要切分的,后头是切分完成的
        queue.addFirst(seq);
        final var maxSize = 25;
        while (true) {
            final var span = queue.poll();// 读取片段
            if (span.size() > maxSize) {
                final var ivp = span.halveP(NVec::new);
                ivp.toList(NVec.of(1)).forEach(e -> {
                    if (e.size() > maxSize)
                        queue.addFirst(e); // 使用队列进行数据切分,不满足要求的放在队列前头
                    else
                        queue.addLast(e); // 满足要求的放在队列尾部
                });//forEach
            } else {
                queue.addLast(span);// 把满足要求的数据再放回去
                break;
            }
        }
        println("数据切分");
        queue.forEach(s -> {
            println(s);
        });
    }

}
